package com.inspur.dgov.vlbod.util;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;

import javax.net.ssl.HostnameVerifier;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 *  自定义公共工具类
 */
@Slf4j
public final class CTools {

    private static long workId;

    static {
        workId = getWorkId();
    }


    public static String getSnowflakeId(){
        return String.valueOf(getLongId());
    }

    public static long getLongId(){
        Snowflake snowflake = IdUtil.getSnowflake(workId, 1);
        return snowflake.nextId();
    }

    /**
     * workId 使用 IP 生成
     * @return
     */
    private static Long getWorkId() {
        try {
            String hostAddress = Inet4Address.getLocalHost().getHostAddress();
            String[] codes = hostAddress.split("\\.");
            int index = codes.length-1;
            int lastCode = Integer.parseInt(codes[index]);
            return (long) (lastCode % 32);
        }catch (UnknownHostException е) {
            return RandomUtils.nextLong(0, 31);
        }
    }


    public static String getUUID(){
        String s = UUID.randomUUID().toString();
        return s.replace("-","");
    }

    public static String dateTimeMillis2String(long time,String format){
        Instant instant = Instant.ofEpochMilli(time);
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone).format(DateTimeFormatter.ofPattern(format));
    }

    /**
     * 对content的内容进行转换后，在作为oracle查询的条件字段值。使用/作为oracle的转义字符,比较合适。<br>
     * 既能达到效果,而且java代码相对容易理解，建议这种使用方式<br>
     * "%'" + content + "'%  ESCAPE '/' "这种拼接sql看起来也容易理解<br>
     * @param content
     * @return
     */
    public static String decodeSpecialCharsWhenLikeUseBackslash(String content){
        // 单引号是oracle字符串的边界,oralce中用2个单引号代表1个单引号
        String afterDecode = content.replaceAll("'", "''");
        // 由于使用了/作为ESCAPE的转义特殊字符,所以需要对该字符进行转义
        // 这里的作用是将"a/a"转成"a//a"
        afterDecode = afterDecode.replaceAll("/", "//");
        // 使用转义字符 /,对oracle特殊字符% 进行转义,只作为普通查询字符，不是模糊匹配
        afterDecode = afterDecode.replaceAll("%", "/%");
        // 使用转义字符 /,对oracle特殊字符_ 进行转义,只作为普通查询字符，不是模糊匹配
        afterDecode = afterDecode.replaceAll("_", "/_");
        return afterDecode;
    }

    public static CloseableHttpClient initHttpClient(){
        // http https
        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
        SSLContextBuilder builder = new SSLContextBuilder ();
        try {
            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
        }catch (NoSuchAlgorithmException | KeyStoreException e) {
            log.error ("Pooling Connection Manager Initialisation failure because of"+ e.getMessage(), e);
        }
        SSLConnectionSocketFactory sslSocketFactory = null;
        try{
            sslSocketFactory = new SSLConnectionSocketFactory (builder.build(),hostnameVerifier);
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            log.error("Pooling Connection Manager Initialisation failure because of" + e.getMessage(), e);
        }
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", sslSocketFactory)
                .build();

        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager( socketFactoryRegistry);
        connManager.setMaxTotal(200);
        connManager.setDefaultMaxPerRoute(100);
        //设置请求默认超时时间
        RequestConfig requestConfig = RequestConfig.custom ()
                .setConnectionRequestTimeout(20000)
                .setConnectTimeout (20000)
                .setSocketTimeout (20000).build();
        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connManager).build();
    }

}
